home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Collections: Franz PD
/
Franz PD Disk #324 (1994-04)(Rhein-Sieg-Soft).zip
/
Franz PD Disk #324 (1994-04)(Rhein-Sieg-Soft).adf
/
VideoText3.5
/
source
/
cct.p
< prev
next >
Wrap
Text File
|
1994-04-01
|
9KB
|
263 lines
UNIT cct; {$project vt }
{ Programmierung des CCT-Chips (Computer Controlled Teletext) SAA5246 }
INTERFACE; FROM vt USES global,i2c_serial;
PROCEDURE display_select(speicher: Byte);
PROCEDURE TV_display(mode: Byte);
FUNCTION VTstat: byte;
PROCEDURE sperren(speicher: Byte);
PROCEDURE anfordern(speicher: Byte; page, subpage: Integer; _mask: Str);
PROCEDURE init_CCT;
FUNCTION seite_da(speicher: Byte): Boolean;
PROCEDURE gettime(speicher: Byte; VAR zeit: Str80);
PROCEDURE gethead(speicher: Byte; VAR head: Str80);
PROCEDURE getpage(speicher: Byte; seite: p_onepage; ganz: Boolean);
{ ---------------------------------------------------------------------- }
IMPLEMENTATION;
{$opt b-}
CONST SAA5246 = $22;
PBLF = $20;
DOCARE = $10;
NOTHOLD = $08;
SERMAG = $0800; { C11 }
VAR i2cdata: Array[1..20] of Byte; { kleiner Puffer für Kommandos }
PROCEDURE display_select{(speicher: Byte)};
{ Einen der 8 Seitenspeicher zur Anzeige auswählen }
begin
setregister(SAA5246,4,speicher);
end;
PROCEDURE TV_display{(mode: Byte)};
{ Art der Anzeige am Fernseher auswählen. }
begin
i2cdata[1] := 5;
case mode of
2: { Normalseiten bildfüllend, Schlagzeilen als Boxen }
begin i2cdata[2] := %11001100; i2cdata[3] := %01001111; end;
1: { Normalseiten als Boxen, Schlagzeilen transparent }
begin i2cdata[2] := %11001111; i2cdata[3] := %00001111; end;
otherwise { Anzeige aus }
begin i2cdata[2] := %00000011; i2cdata[3] := %00000011; end;
end;
i2cdata[4] := %00000111;
i2cbusIO(SAA5246,^i2cdata,4);
end;
FUNCTION VTstat{: byte};
{ Liest aus dem CCT das Register R11B. Bedeutung: bit0 - Videosignal vorh., }
{ bit1 - Textsignal vorh., bit2-5 - ROM-Version }
begin
setregister(SAA5246,0,%00000001); { R11B aktivieren }
VTstat := getregister(SAA5246,11); { Status lesen }
setregister(SAA5246,0,%00000000); { R11 aktivieren }
end;
PROCEDURE sperren{(speicher: Byte)};
{ Seitensuche eines Empfangskreises anhalten, damit nicht evtl. niederpriore }
{ Empfangskreise behindert werden. Die Sperre wird bei Programmierung einer }
{ neuen Seitenanforderung automatisch aufgehoben. }
begin
i2cdata[1] := 2;
i2cdata[2] := speicher*16;
i2cdata[3] := 0;
i2cbusIO(SAA5246,^i2cdata,3);
end;
PROCEDURE anfordern{(speicher: Byte; page, subpage: Integer; _mask: Str)};
{ Einlesen einer Seite in einen Seitenspeicher 0..7 anfordern, Unterseite nur }
{ direkt anfordern, wenn subpage <> 0 }
{ <_mask> ist ein dreistelliger String, wo ein '*' steht, wird in der }
{ entsprechenden Ziffer der angeforderten Seitennummer das DOCARE-Bit }
{ gelöscht. }
VAR lauf: integer;
mask: String[10];
begin
mask := _mask;
{ Seitenanforderung beschreiben: }
i2cdata[1] := 2;
i2cdata[2] := speicher*16;
i2cdata[3] := ((page div 100) mod 8) OR NOTHOLD;
i2cdata[4] := (page div 10) mod 10;
i2cdata[5] := page mod 10;
if page <> 0 then
for lauf := 3 to 5 do
if mask[lauf-2]<>'*' then
i2cdata[lauf] := i2cdata[lauf] or DOCARE;
i2cdata[6] := subpage div 1000;
i2cdata[7] := (subpage div 100) mod 10;
i2cdata[8] := (subpage div 10) mod 10;
i2cdata[9] := subpage mod 10;
if subpage <> 0 then
for lauf := 6 to 9 do i2cdata[lauf] := i2cdata[lauf] or DOCARE;
i2cbusIO(SAA5246,^i2cdata,9)
end;
PROCEDURE init_CCT;
var i: byte;
begin
{ Wichtig in R1: bit5 - ACQ OFF, Decoder-NotAus; bit2 - TCS ON, }
{ RGB-Ausgangssignal wird mit Fernsehbild synchronisiert. }
setregister(SAA5246,1,%00000100);
{ Seitensuche sperren: }
for i := 0 to maxactive-1 do sperren(i);
{ alle Seitenspeicher löschen: }
for i := 0 to 7 do begin
setregister(SAA5246,8,%00001000 or i); delay(2);
{ Löschvorgang dauert bis zu 22 ms, darum mal jeweils 40 ms warten. }
end;
{ R11 aktivieren }
setregister(SAA5246,0,%00000000);
{ Fernsehdarstellung einschalten }
display_select(0);
TV_display(2);
end;
FUNCTION seite_da{(speicher: Byte): Boolean};
{ Überprüft, ob die für einen Speicher 0..7 angeforderte Seite bereits }
{ eingetroffen ist. Das Statusflag PBLF, das in diesem Fall gelöscht ist, }
{ muß danach wieder gesetzt werden. Das geschieht entweder implizit beim }
{ Programmieren einer neuen Seitenanforderung oder explizit durch }
{ Schreibzugriff, in diesem Programm in getpage(). }
{ Problem: das Statusflag PBLF bezieht sich auf den Empfang der Kopfzeile, }
{ nicht etwa den Empfang der kompletten Seite. Genauer gesagt: für letzteres }
{ existiert überhaupt kein Statusflag! }
{ Nun ist das nicht ganz so tragisch, nach Empfang der Kopfzeile kann man }
{ bereits bedenkenlos die Statuszeile 25 mit Steuerbits und Seitennummer }
{ lesen. Und in vielen Fällen geht es sogar gut, sofort mit dem Einlesen }
{ der gesamten Seite zu beginnen, da sich nämlich maximal 11 Seiten pro }
{ Sekunde über den I²C-Bus schaufeln lassen, während der Videotext selbst }
{ mit ca. 13 Seiten pro Sekunde einrollt: Die noch leere Seite wird }
{ schneller aufgefüllt, als sie ausgelesen werden kann. }
{ Probleme entstehen natürlich, wenn der Empfang der VT-Seite länger als }
{ ca. 1/10 s dauert. Das ist möglich, wenn der Sender nicht alle zur }
{ VT-Übertragung zulässigen Rasterzeilen ausnutzt, oder wenn er gar den }
{ Magazin-gemischten Übertragungsmodus verwendet. Letzteres ist aber an }
{ einem Statusflag (C11) vom Programm aus erkennbar, hm ... }
begin
seite_da := false;
{ Byte 9 der Statuszeile (Zeile 25) adressieren ... }
i2cdata[1] := 8;
i2cdata[2] := speicher;
i2cdata[3] := 25; i2cdata[4] := 9;
i2cbusIO(SAA5246,^i2cdata,4);
if i2c_status<>0 then
exit; { Schreibfehler }
{ ... und auslesen: }
i2cbusIO(SAA5246,^i2cdata,-1);
if i2c_status<>0 then
exit; { Lesefehler }
seite_da := (i2cdata[1] AND PBLF)=0;
end;
PROCEDURE gettime{(speicher: Byte; VAR zeit: Str80)};
{ liest aus einer Speicherseite 0..7 des CCT-Bausteins die Uhrzeit }
var i: integer;
begin
zeit := '00:00:00';
{ Uhrzeit aus der Seite im CCT lesen: Zeile 0, Spalte 32 }
i2cdata[1] := 8;
i2cdata[2] := speicher;
i2cdata[3] := 0; i2cdata[4] := 32;
i2cbusIO(SAA5246,^i2cdata,4);
if i2c_status<>0 then
exit; { Schreibfehler }
{ Uhrzeit lesen: }
i2cbusIO(SAA5246,^i2cdata,-8);
if i2c_status<>0 then
exit; { Lesefehler }
for i := 1 to 8 do
IF i2cdata[i] IN [32..127] THEN zeit[i] := chr(i2cdata[i]);
end;
PROCEDURE gethead{(speicher: Byte; VAR head: Str80)};
{ liest die 24 Byte Titelzeile zwischen Statusfeld und Uhrzeit }
var i: integer;
begin
head := '';
{ Seitenspeicher addressieren: Zeile 0, Spalte 8 }
i2cdata[1] := 8;
i2cdata[2] := speicher;
i2cdata[3] := 0; i2cdata[4] := 8;
i2cbusIO(SAA5246,^i2cdata,4);
if i2c_status<>0 then
exit; { Schreibfehler }
{ Zeile lesen: }
i2cbusIO(SAA5246,^head,-24);
if i2c_status<>0 then
exit; { Lesefehler }
for i := 1 to 24 do
IF NOT (ord(head[i]) IN [32..127]) THEN head[i] := ' ';
head[25] := #0;
end;
PROCEDURE getpage{(speicher: Byte; seite: p_onepage; ganz: Boolean)};
{ Liest eine Speicherseite (0..7) aus dem CCT-Baustein aus und speichert }
{ diese Seite im Amiga. Für <ganz>=false werden nur die Statusinformationen }
{ aus Zeile 25 gelesen. }
{ Abschließend wird das Statusflag PBLF wieder gesetzt! }
VAR i,h: Integer;
status: ARRAY [0..9] OF Byte;
s: str80;
BEGIN
{ Status aus der Seite im CCT lesen: Zeile 25, Spalte 0 }
i2cdata[1] := 8;
i2cdata[2] := speicher;
i2cdata[3] := 25; i2cdata[4] := 0;
i2cbusIO(SAA5246,^i2cdata,4);
if i2c_status<>0 then
exit; { Schreibfehler }
i2cbusIO(SAA5246,^status,-10);
if i2c_status<>0 then
exit; { Lesefehler }
seite^.pg := (status[0] and $F) + 10*(status[1] and $F) + 100*(status[8] and $7);
if seite^.pg<100 then seite^.pg := seite^.pg + 800;
seite^.sp := (status[2] and $F) + 10 * (status[3] and $7)
+ 100 * (status[4] and $F) + 1000 * (status[5] and $3);
seite^.cbits := (status[3] AND $08) SHL 1 { C4 }
+ (status[5] AND $0C) SHL 3 { C5, C6 }
+ (status[6] AND $0F) SHL 7 { C7, C8, C9, C10 }
+ (status[7] AND $0F) SHL 11 { C11, C12..C14 }
if ganz then begin
{ Seite aus CCT lesen. Richtigen Speicher, Zeile 0, Spalte 0 adressieren: }
i2cdata[1] := 8;
i2cdata[2] := speicher;
i2cdata[3] := 0; i2cdata[4] := 0;
i2cbusIO(SAA5246,^i2cdata,4);
if i2c_status<>0 then begin
exit; { Schreibfehler }
end;
{ Seite einlesen: }
i2cbusIO(SAA5246,^seite^.chars,-960);
if i2c_status<>0 then begin
exit; { Lesefehler }
end;
{ in den freien Anfang der 1. Zeile die Unterseitennummer eintragen }
seite^.chars[1] := ord('(');
seite^.chars[2] := (status[5] and $3)+ord('0');
seite^.chars[3] := (status[4] and $F)+ord('0');
seite^.chars[4] := (status[3] and $7)+ord('0');
seite^.chars[5] := (status[2] and $F)+ord('0');
seite^.chars[6] := ord(')');
seite^.chars[7] := ord(' ');
IF status[7] AND $01=0 THEN BEGIN { C11=0: Magazin-gemischte Übertragung, }
seite^.chars[1] := ord('<'); { Modus für den Benutzer erkennbar machen }
seite^.chars[6] := ord('>');
END;
{ aus dem zur Anzeige aktivierten Seitenspeicher die Uhrzeit holen: }
if speicher<>aktspeicher then begin
gettime(aktspeicher,s);
for i := 1 to 8 do
seite^.chars[31+i] := ord(s[i]);
END;
END;
END;
BEGIN { Initialisierungsteil }
END.